Skip to content

fix(auth): select signing algorithm explicitly for self-certifying DIDs#4

Merged
pauldelucia merged 1 commit into
masterfrom
fix/secp256k1-algorithm-detection
Jul 2, 2026
Merged

fix(auth): select signing algorithm explicitly for self-certifying DIDs#4
pauldelucia merged 1 commit into
masterfrom
fix/secp256k1-algorithm-detection

Conversation

@pauldelucia

Copy link
Copy Markdown
Contributor

Problem

Willow DIDs are now self-certifying:

did:willow:z<base58btc(SHA3-256(multicodec || pubkey))>

They no longer embed the key algorithm (the retired format was did:willow:<alg>:<pubkey>, e.g. did:willow:ed25519:.. / did:willow:secp256k1:..).

detect_algorithm_from_did parsed the algorithm out of the DID string and was used by sign_request (per-request auth) and the consensus client's transaction signing to choose Ed25519 vs secp256k1. With a self-certifying id that parse is impossible, so it silently defaults to Ed25519. A secp256k1 (Ethereum/wallet) identity then signs per-request auth and consensus transactions with the wrong algorithm and is rejected. Ed25519-first identities (the SDK default) were unaffected, which masked the bug.

Reproduced before the fix: for a freshly generated secp256k1 identity, detect_algorithm_from_did(did) returns Ed25519 and the resulting per-request signature fails secp256k1 verification.

Fix

Thread an explicit algorithm argument (default "Ed25519", fully backward compatible) through the signing paths, instead of inferring it from the DID string:

  • auth.sign_request(..., algorithm="Ed25519")
  • WillowClient.set_identity(..., algorithm="Ed25519") — stored on the client and passed to its three sign_request call sites; reset by clear_identity.
  • ConsensusClient signing methods (register_did, register_subgrove, transfer, store_data, store_file_manifest, delete_file_manifest, deregister_subgrove) → _sign_and_broadcast(..., algorithm="Ed25519").

The new parameter is appended (or placed after the existing trailing optional) in every signature, so existing positional and keyword calls are unaffected.

detect_algorithm_from_did is retained (it still parses the retired did:willow:<alg>:<pubkey> format and remains exported) but is no longer used to choose a signing algorithm and is documented as deprecated. The DID string is unchanged — the algorithm is not reintroduced into it.

Tests

  • tests/test_auth.py: sign_request selects secp256k1 for a secp256k1 identity (signature verifies under secp256k1 and would NOT verify under the old Ed25519 default); Ed25519 still defaults; a self-certifying secp256k1 DID is documented as not algorithm-detectable.
  • tests/test_client.py: set_identity(..., "secp256k1") is stored/reset; an end-to-end authenticated request (mocked transport) captures the signed headers and confirms the signature verifies as secp256k1, not Ed25519.

Full suite: 295 passed, 13 skipped (the skips are pre-existing integration tests).

🤖 Generated with Claude Code

Willow DIDs are now self-certifying
(did:willow:z<base58btc(SHA3-256(multicodec||pubkey))>) and no longer embed
the key algorithm in the string. detect_algorithm_from_did could therefore no
longer recover it and silently defaulted to Ed25519, so a secp256k1
(Ethereum/wallet) identity signed per-request auth and consensus transactions
with the wrong algorithm and was rejected by the server.

Thread an explicit `algorithm` argument (default "Ed25519", backward
compatible) through the signing paths:
  - auth.sign_request
  - WillowClient.set_identity -> stored and passed to its three
    sign_request call sites
  - ConsensusClient signing methods -> _sign_and_broadcast

detect_algorithm_from_did is retained (it still parses the retired
did:willow:<alg>:<pubkey> format) but is no longer used to choose a signing
algorithm and is documented as deprecated. The DID string is unchanged.

Add regression tests proving a secp256k1 identity signs with secp256k1 (and
would NOT verify under the old Ed25519 default) and that Ed25519 still
defaults correctly, at both the auth.sign_request and WillowClient levels.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pauldelucia pauldelucia merged commit a985e5c into master Jul 2, 2026
1 check passed
@pauldelucia pauldelucia deleted the fix/secp256k1-algorithm-detection branch July 2, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants